package pers.dawnyang.modular.system.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import pers.dawnyang.common.annotation.SP;
import pers.dawnyang.common.constant.Const;
import pers.dawnyang.common.domain.entity.SysDept;
import pers.dawnyang.common.domain.entity.SysUser;
import pers.dawnyang.common.domain.entity.SysUserDept;
import pers.dawnyang.common.domain.entity.SysUserRole;
import pers.dawnyang.common.enums.ConfigEnum;
import pers.dawnyang.common.util.MyTools;
import pers.dawnyang.common.util.math.RandomUtil;
import pers.dawnyang.config.cache.ConfigUtils;
import pers.dawnyang.config.shiro.ShiroUtil;
import pers.dawnyang.modular.system.domain.request.user.UserDeptReqU;
import pers.dawnyang.modular.system.domain.request.user.UserReqR;
import pers.dawnyang.modular.system.domain.request.user.UserRoleReqU;
import pers.dawnyang.modular.system.domain.response.user.UserDeptRes;
import pers.dawnyang.modular.system.domain.response.user.UserExcelRes;
import pers.dawnyang.modular.system.domain.response.user.UserRes;
import pers.dawnyang.modular.system.domain.response.user.UserRoleRes;
import pers.dawnyang.modular.system.mapper.SysDeptMapper;
import pers.dawnyang.modular.system.mapper.SysUserDeptMapper;
import pers.dawnyang.modular.system.mapper.SysUserMapper;
import pers.dawnyang.modular.system.mapper.SysUserRoleMapper;
import pers.dawnyang.modular.system.service.UserService;

/**
 * @author dawn
 * @date 2021/02/08
 */
@Service
public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements UserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysUserDeptMapper sysUserDeptMapper;

    @SP
    @Override
    public Page<UserRes> getPage(Page<UserRes> page, UserReqR req) {
        // SqlTools.montageSql(req);
        Page<UserRes> resPage = sysUserMapper.getPage(page, req);
        return resPage;
    }

    @Override
    public List<SysUserDept> getUserDeptList(Long userId) {
        LambdaQueryWrapper<SysUserDept> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysUserDept::getUserId, userId);
        return sysUserDeptMapper.selectList(lqw);
    }

    @Override
    public void saveUserRole(UserRoleReqU req) {
        Long userId = req.getUserId();
        String lastRoleIds = req.getLastRoleIds();
        String roleIds = req.getRoleIds();
        List<String> add = MyTools.getDiff(lastRoleIds, roleIds);
        if (add != null && add.size() > 0) {
            for (String str : add) {
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setUserId(userId);
                sysUserRole.setRoleId(Long.valueOf(str));
                sysUserRoleMapper.insert(sysUserRole);
            }
        }
        List<String> delete = MyTools.getDiff(roleIds, lastRoleIds);
        if (delete != null && delete.size() > 0) {
            for (String str : delete) {
                LambdaQueryWrapper<SysUserRole> lqw = new LambdaQueryWrapper<>();
                lqw.eq(SysUserRole::getRoleId, Long.valueOf(str));
                lqw.eq(SysUserRole::getUserId, userId);
                sysUserRoleMapper.delete(lqw);
            }
        }

    }

    @Override
    public List<UserDeptRes> getUserDept(Long userId) {
        List<UserDeptRes> allDept = sysUserMapper.getAllDept();
        List<UserDeptRes> userDept = sysUserMapper.getUserDept(userId);
        allDept.forEach(res -> {
            if (userDept.contains(res)) {
                res.setCheckArr("1");
            } else {
                res.setCheckArr("0");
            }
        });
        return allDept;
    }

    @Override
    public List<UserRoleRes> getUserRole(Long userId) {
        List<UserRoleRes> allRole = sysUserMapper.getAllRole();
        List<UserRoleRes> userRole = sysUserMapper.getUserRole(userId);

        allRole.forEach(res -> {
            if (userRole.contains(res)) {
                res.setLAY_CHECKED(true);
            } else {
                res.setLAY_CHECKED(false);
            }
        });

        return allRole;
    }

    @Override
    public void saveUserDept(UserDeptReqU req) {
        Long userId = req.getUserId();
        String lastDeptIds = req.getLastDeptIds();
        String deptIds = req.getDeptIds();
        List<String> add = MyTools.getDiff(lastDeptIds, deptIds);
        if (add != null && add.size() > 0) {
            for (String str : add) {
                SysUserDept sysUserDept = new SysUserDept();
                sysUserDept.setUserId(userId);
                sysUserDept.setDeptId(Long.valueOf(str));
                sysUserDeptMapper.insert(sysUserDept);
            }
        }
        List<String> delete = MyTools.getDiff(deptIds, lastDeptIds);
        if (delete != null && delete.size() > 0) {
            for (String str : delete) {
                LambdaQueryWrapper<SysUserDept> lqw = new LambdaQueryWrapper<>();
                lqw.eq(SysUserDept::getDeptId, Long.valueOf(str));
                lqw.eq(SysUserDept::getUserId, userId);
                sysUserDeptMapper.delete(lqw);
            }
        }
    }

    @Override
    public UserRes getUserDetail(Long userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);
        UserRes userRes = new UserRes();
        BeanUtils.copyProperties(sysUser, userRes);
        List<UserRoleRes> userRole = sysUserMapper.getUserRole(userId);
        // List<UserDeptRes> userDept = sysUserMapper.getUserDept(userId);

        List<UserDeptRes> userDept = new ArrayList<>();
        LambdaQueryWrapper<SysUserDept> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysUserDept::getUserId, userId);
        List<SysUserDept> resList = sysUserDeptMapper.selectList(lqw);
        if (null != resList && resList.size() > 0) {
            for (SysUserDept sysUserDept : resList) {
                UserDeptRes userDeptRes = new UserDeptRes();
                Long deptId = sysUserDept.getDeptId();
                SysDept sysDept = sysDeptMapper.selectById(deptId);
                String deptName = sysDept.getDeptName();
                String pids = sysDept.getPids();
                String[] pidArr = pids.split(",");
                String pDeptName = "";
                for (String pid : pidArr) {
                    if (!"0".equals(pid)) {
                        SysDept sysDeptP = sysDeptMapper.selectById(pid);
                        if (null != sysDeptP) {
                            pDeptName += sysDeptP.getDeptName() + "/";
                        }
                    }
                }
                pDeptName += deptName;
                userDeptRes.setDeptId(deptId);
                userDeptRes.setDeptName(pDeptName);
                userDept.add(userDeptRes);
            }

        }

        userRes.setRoleList(userRole);
        userRes.setDeptList(userDept);
        return userRes;
    }

    @Override
    public void resetPwd(Long userId) {
        String salt = RandomUtil.getRandomString(Const.SALT_FIGURE);
        String defaultPwd = ConfigUtils.getValue(ConfigEnum.DEFAULT_PWD.getConfigCode());
        String newPwdMd5Hash = new Md5Hash(defaultPwd, salt, Const.MD5_NUM).toString();
        SysUser user = new SysUser();
        user.setPassword(newPwdMd5Hash);
        user.setSalt(salt);
        LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysUser::getUserId, userId);
        sysUserMapper.update(user, lqw);
    }

    @SP
    @Override
    public List<UserExcelRes> export(UserReqR req) {
        List<UserExcelRes> records = sysUserMapper.getUserExcel(req);
        return records;
    }

    @Override
    public Long getUserMinRoleLevel(Long userId) {
        return sysUserMapper.getUserMinRoleLevel(userId);
    }

    @Override
    public boolean checkRoleLevel(Long userId) {
        if (userId != ShiroUtil.getUserId()) {
            Long minRoleLevel = ShiroUtil.getUserMinRoleLevel();
            Long roleLevel = sysUserMapper.getUserMinRoleLevel(userId);
            if (null != roleLevel) {
                if (roleLevel <= minRoleLevel) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public Long getMinRoleLevelByRoleIds(String roleIds) {
        String[] roleIdsArr = roleIds.split(",");
        return sysUserMapper.getMinRoleLevelByRoleIds(roleIdsArr);
    }

}
